MongoDB是什么 ?

  • MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
  • 在高负载的情况下,添加更多的节点,可以保证服务器性能。
  • MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
1
2
3
4
5
{
user: "admin", --->key=>value
pwd: "123456", --->key=>value
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}

主要特点

  • MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
  • 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=”Sameer”,Address=”8 Gandhi Road”)来实现更快的排序。
  • 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
  • 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
  • Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
  • MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
  • Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
  • Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
  • Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
  • GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
  • MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
  • MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
  • MongoDB安装简单。

MongoDB管理 工具

  • Fang of Mongo – 网页式,由Django和jQuery所构成。
  • Futon4Mongo – 一个CouchDB Futon web的mongodb山寨版。
  • Mongo3 – Ruby写成。
  • MongoHub – 适用于OSX的应用程序。
  • Opricot – 一个基于浏览器的MongoDB控制台, 由PHP撰写而成。
  • Database Master — Windows的mongodb管理工具
  • RockMongo — 最好的PHP语言的MongoDB管理工具,轻量级, 支持多国语言.

MongoDB 基本概念

在mongodb中基本的概念是文档、集合、数据库

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

通过下图实例,我们也可以更直观的了解Mongo中的一些概念:

数据库

一个mongodb中可以建立多个数据库。MongoDB的默认数据库为”db”,该数据库存储在data目录中。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。

1
2
3
4
5
6
7
8
9
> show dbs   # 命令可以显示所有数据的列表。
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
> db # 显示当前数据库对象或集合。
test
> use demo # 连接到一个指定的数据库。
switched to db demo

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin: 从权限的角度来看,这是”root”数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

文档(Document)

文档是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

1
{"site":"www.zysheep.cn", "name":"三月三"}

下表列出了 RDBMS 与 MongoDB 对应的术语:

RDBMS MongoDB
数据库 数据库
表格 集合
文档
字段
表联合 嵌入文档
主键 主键 (MongoDB 提供了 key 为 _id )

需要注意的是:

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:

  • 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
  • .和$有特别的意义,只有在特定环境下才能使用。
  • 以下划线”_”开头的键是保留的(不是严格要求的)。

集合

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

比如,我们可以将以下不同数据结构的文档插入到集合中:

1
2
3
{"site":"www.baidu.com"}
{"site":"www.zysheep.cn","name":"三月三"}
{"site":"www.zysheep.cn","name":"三月三热爱生活","num":5}

合法的集合名

  • 集合名不能是空字符串””。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以”system.”开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。 

如下实例:

1
db.col.findOne()

capped collections

Capped collections 就是固定大小的collection。它有很高的性能以及队列过期的特性(过期按照插入的顺序). 有点和 “RRD” 概念类似。Capped collections 是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能和标准的 collection 不同,你必须要显式的创建一个capped collection,指定一个 collection 的大小,单位是字节。collection 的数据存储空间值提前分配的。

1
db.createCollection("mycoll", {capped:true, size:100000})
  • 在 capped collection 中,你能添加新的对象。
  • 能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。
  • 使用 Capped Collection 不能删除一个文档,可以使用 drop() 方法删除 collection 所有的行。
  • 删除之后,你必须显式的重新创建这个 collection。
  • 在32bit机器中,capped collection 最大存储为 1e9( 1X109)个字节。

元数据

数据库的信息是存储在集合中。它们使用了系统的命名空间:

1
dbname.system.*

在MongoDB数据库中名字空间 .system.* 是包含多种系统信息的特殊集合(Collection),如下:\

集合命名空间 描述
dbname.system.namespaces 列出所有名字空间。
dbname.system.indexes 列出所有索引。
dbname.system.profile 包含数据库概要(profile)信息。
dbname.system.users 列出所有可访问数据库的用户。
dbname.local.sources 包含复制对端(slave)的服务器信息和状态。

MongoDB 数据类型

数据类型 描述
String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。

ObjectId

ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:

  • 前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
  • 接下来的 3 个字节是机器标识码
  • 紧接的两个字节由进程 id 组成 PID
  • 最后三个字节是随机数

MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象

由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:

1
2
3
> var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2020-06-02T00:41:51Z")

ObjectId 转为字符串

1
2
> newObject.str
5ed5a04fb5ebb889810105cf

字符串

BSON 字符串都是 UTF-8 编码。

时间戳

BSON 有一个特殊的时间戳类型用于 MongoDB 内部使用,与普通的 日期 类型不相关。 时间戳值是一个 64 位的值。其中:

  • 前32位是一个 time_t 值(与Unix新纪元相差的秒数)
  • 后32位是在某秒中操作的一个递增的序数

在单个 mongod 实例中,时间戳值通常是唯一的。在复制集中, oplog 有一个 ts 字段。这个字段中的值使用BSON时间戳表示了操作时间。

BSON 时间戳类型主要用于 MongoDB 内部使用。在大多数情况下的应用开发中,你可以使用 BSON 日期类型。

日期

表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。

1
2
3
4
5
> var mydate1 = new Date() 
> mydate1
ISODate("2020-06-02T00:43:59.056Z")
> typeof mydate1
object

这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。

返回一个时间类型的字符串:

1
2
3
4
5
>  var mydate1str = mydate1.toString()
> mydate1str
Tue Jun 02 2020 00:43:59 GMT+0000 (UTC)
> typeof mydate1str
string

或者

1
2
> Date()
Tue Jun 02 2020 00:45:23 GMT+0000 (UTC)

MongoDB基本命令

MongoDB 创建数据库

语法

1
use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切换到指定数据库。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> use zysheep  # 创建数据库zysheep
switched to db zysheep
> show dbs # 查看所有数据库
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
> db.zysheep.insert({"sate":"zysheep"})
# 创建的数据库 zysheep 并不在数据库的列表中, 要显示它,我们需要向 zysheep 数据库插入一些数据。
WriteResult({ "nInserted" : 1 })
> show dbs
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
zysheep 0.000GB
> db # 查看当前所在数据库
zysheep

MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。

注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建

MongoDB 删除数据库

语法

1
db.dropDatabase()

删除当前数据库,默认为test,你可以使用 db 命令查看当前数据库名。

实例

以下实例我们删除了数据库 zysheep。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> show dbs  # 查看所有数据库
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
zysheep 0.000GB
> db # 查看当前数据库
zysheep
> db.dropDatabase() # 删除当前数据库
{ "dropped" : "zysheep", "ok" : 1 }
> show dbs # 查看是否删除
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB

删除集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> show dbs
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
> use zysheep
switched to db zysheep
> db.createCollection("zysheep") # 先创建集合,类似数据库中的表
{ "ok" : 1 }
> show tables # show collections 命令会更加准确点
zysheep
> db.zysheep.drop()
true
> show tables

MongoDB 创建集合

语法

1
db.createCollection(name, options)
  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项

options 可以是如下参数:

字段 类型 描述
capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。
autoIndexId 布尔 (可选)如为 true,自动在 _id 字段创建索引。默认为 false。
size 数值 (可选)为固定集合指定一个最大值,以千字节计(KB)。 如果 capped 为 true,也需要指定该字段。
max 数值 (可选)指定固定集合中包含文档的最大数量。

在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> use demo #创建 demo 数据库
switched to db demo
> db.createCollection("demo") # 创建 demo 集合
{ "ok" : 1 }
> show collections # 查看已有集合
demo
info
> show tables # 查看已有集合
demo
info
> db.createCollection("mycol", { capped : true, autoIndexId : true, size :
... 6142800, max : 10000 } ) # 创建固定集合 mycol
{
"note" : "the autoIndexId option is deprecated and will be removed in a future release",
"ok" : 1
}
> show tables # 查看已有集合
demo
info
mycol
> db.myclo2.insert({"name":"三月三"})
# 在 MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。
WriteResult({ "nInserted" : 1 })
> show tables
demo
info
myclo2
mycol

MongoDB 删除集合

语法

1
db.collection.drop()

如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

实例

在数据库mydb中,我们可以先通过 show collections 命令查看已存在的集合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> use demo  # 使用demo数据库
switched to db demo
> show tables # 查看当前数据库所有集合
demo
info
myclo2
mycol
> db.demo.drop() # 删除demo集合
true
> show tables;
info
myclo2
mycol
>

MongoDB 插入文档

文档的数据结构和 JSON基本一样。所有存储在集合中的数据都是BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON的简称。

语法

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

1
2
3
db.COLLECTION_NAME.insert(document)

db.COLLECTION_NAME.save(document)
  • save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne()db.collection.replaceOne() 来代替。
  • insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据

3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。

db.collection.insertOne() 用于向集合插入一个新文档,语法格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 语法
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
# 实例
> var document = db.collection.insertOne({"a": 3})
> document
{
"acknowledged" : true,
"insertedId" : ObjectId("5ed5a93256fa4269b4e255ff")
}

db.collection.insertMany() 用于向集合插入一个多个文档,语法格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 语法
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
# 实例
> var res = db.collection.insertMany([{"b": 3}, {'c': 4}])
> res
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5ed5a93f56fa4269b4e25600"),
ObjectId("5ed5a93f56fa4269b4e25601")
]
}
  • document:要写入的文档。
  • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
  • ordered:指定是否按顺序写入,默认 true,按顺序写入。

实例

以下文档可以存储在 MongoDB 的 demo数据库 的 col 集合中:

1
2
3
4
5
6
7
8
>db.col.insert({title: 'MongoDB 教程', 
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
>WriteResult({ "nInserted" : 1 })

以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

查看已插入文档:

1
2
> db.col.find()
>{ "_id" : ObjectId("5ed5a7e356fa4269b4e255fd"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }

我们也可以将数据定义为一个变量,如下所示:

1
2
3
4
5
6
7
document=({title: 'MongoDB 教程', 
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
});

执行后显示结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

执行插入操作:

1
2
>db.col.insert(document)
WriteResult({ "nInserted" : 1 })

插入文档你也可以使用 db.col.save(document)命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

MongoDB 更新文档

MongoDB 使用 update()save() 方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。

update() 方法

语法

update() 方法用于更新已存在的文档。语法格式如下:

1
2
3
4
5
6
7
8
9
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc…)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。

实例

我们在集合 col 中插入如下数据:

1
2
3
4
5
6
7
8
9
db.col.insert({
title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
WriteResult({ "nInserted" : 1 })

接着我们通过 update() 方法来更新标题(title):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.col.find().pretty()
{
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

可以看到标题(title)由原来的 “MongoDB 教程” 更新为了 “MongoDB”。

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

1
>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})

save() 方法

语法

save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。

1
2
3
4
5
6
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
  • document : 文档数据。
  • writeConcern :可选,抛出异常的级别。

实例

以下实例中我们替换了 _id 为 5ed5a7e356fa4269b4e255fd的文档数据:

原数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.col.find().pretty()
{
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

执行更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
db.col.save({
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB_Zysheep",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Zysheep",
"url" : "http://www.zysheep.cn",
"tags" : [
"mongodb",
"NoSQL",
"zysheep"
],
"likes" : 120
})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

替换成功后,我们可以通过 find() 命令来查看替换后的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
db.col.find().pretty()
{
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB_Zysheep",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Zysheep",
"url" : "http://www.zysheep.cn",
"tags" : [
"mongodb",
"NoSQL",
"zysheep"
],
"likes" : 120
}

MongoDB 删除文档

MongoDB remove()函数是用来移除集合中的数据。MongoDB数据更新可以使用update()函数。在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯。

语法

1
2
3
4
db.collection.remove(
<query>,
<justOne>
)
  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

实例

1
2
3
4
5
6
7
8
9
10
# 查询所有数据
> db.col.find()
{ "_id" : ObjectId("5ed5a7e356fa4269b4e255fd"), "title" : "MongoDB_Zysheep", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "Zysheep", "url" : "http://www.zysheep.cn", "tags" : [ "mongodb", "NoSQL", "zysheep" ], "likes" : 120 }
{ "_id" : ObjectId("5ed5a81856fa4269b4e255fe"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
{ "_id" : ObjectId("5ed5aa2156fa4269b4e25602"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
# 移除 title 为 'MongoDB' 的文档
>db.col.remove({'title':'MongoDB'})
WriteResult({ "nRemoved" : 2 })
# 再次查询所有文档
>db.col.find()

如果你只想删除第一条找到的记录可以设置 justOne 为 1

1
>db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)

注意

remove()方法已经过时了,现在官方推荐使用deleteOne()deleteMany()方法。

如删除集合下全部文档:

1
db.COLLECTION_NAME.deleteMany({})

删除 status 等于 A 的全部文档:

1
db.COLLECTION_NAME.deleteMany({ status : "A" })

删除 status 等于 D 的一个文档:

1
db.COLLECTION_NAME.deleteOne( { status: "D" } )

MongoDB 查询文档

MongoDB 查询文档使用 find() 方法。

语法

1
>db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件
  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

1
>db.col.find().pretty()

pretty()方法以格式化的方式来显示所有文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.col.find().pretty()
{
"_id" : ObjectId("56063f17ade2f21f36b03133"),
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

MongoDB 与 RDBMS Where 语句比较

操作 格式 范例 RDBMS中的类似语句
等于 {<key>:<value>} db.col.find({"by":"菜鸟教程"}).pretty() where by = '菜鸟教程'
小于 {<key>:{$lt:<value>}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
小于或等于 {<key>:{$lte:<value>}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
大于 {<key>:{$gt:<value>}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
大于或等于 {<key>:{$gte:<value>}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
不等于 {<key>:{$ne:<value>}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50

MongoDB中条件操作符有:

  • (>) 大于 - $gt
  • (<) 小于 - $lt
  • (>=) 大于等于 - $gte
  • (<= ) 小于等于 - $lte

MongoDB AND 条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

语法格式如下:

1
>db.col.find({key1:value1, key2:value2}).pretty()

#####实例

以下实例通过 bytitle 键来查询 菜鸟教程MongoDB 教程 的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.col.find({"by":"菜鸟教程", "title":"MongoDB 教程"}).pretty()
{
"_id" : ObjectId("56063f17ade2f21f36b03133"),
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

以上实例中类似于 WHERE 语句:WHERE by=’菜鸟教程’ AND title=’MongoDB 教程’

MongoDB OR 条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

1
2
3
4
5
6
7
>db.col.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
实例

以下实例中,我们演示了查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{
"_id" : ObjectId("56063f17ade2f21f36b03133"),
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: ‘where likes>50 AND (by = ‘菜鸟教程’ OR title = ‘MongoDB 教程’)’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{
"_id" : ObjectId("56063f17ade2f21f36b03133"),
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}

docker 部署 mongodb

拉取镜像

1
docker pull mongo

可以查看镜像是否下载成功

1
docker images | grep mongo

1591003616968

docker 安装 mongodb

1
docker run --name mongodb -v /data/mongodb0:/data/db -p 27017:27017 -d mongo

执行上述命令之后, 一个挂载了 mongo镜像的容器就开始运行了

  • --name 设置了容器的名字
  • -v 设置了路径的映射, 将本地路径映射到容器中. 此处, 路径可以自定义
  • -p 设置了端口的映射, 将容器的27017(右侧) 映射到了本地的27017(右侧)

进入容器.

1
docker exec -it mongodb bash

上述命令的意思如下:使用交互的形式, 在 名字为 mongodb 的容器中实行 bash这个命令

mongodb的使用

用户的创建

输入以下命令进入 mongo

创建用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 # 进入 admin 的数据库
> use admin
switched to db admin
# 创建管理员用户
> db.createUser(
... {
... user: "admin",
... pwd: "123456",
... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
... }
... )
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
# 创建有可读写权限的用户. 对于一个特定的数据库, 比如'demo'
> db.createUser({
... user: 'test',
... pwd: '123456',
... roles: [{role: "read", db: "demo"}]
... })
Successfully added user: {
"user" : "test",
"roles" : [
{
"role" : "read",
"db" : "demo"
}
]
}

数据库的建立

1
use demo;

mongo 是否正常启动的校验

先写入一条数据

1
db.info.save({name: 'test', age: '22'})

查看写入的数据

1
db.info.find();

结果如下

1
2
3
4
5
6
7
8
9
# 数据库的建立
> use demo;
switched to db demo
# 先写入一条数据
> db.info.save({name: 'test', age: '22'})
WriteResult({ "nInserted" : 1 })
#
> db.info.find();
{ "_id" : ObjectId("5ed4cc9c3f1db5d1d0e02f01"), "name" : "test", "age" : "22" }

远程连接的开启

mongodb 的容器当中

1
2
3
4
5
6
#更新源
apt-get update
# 安装 vim
apt-get install vim
# 修改 mongo 配置文件
vim /etc/mongod.conf.orig

将其中的bindIp: 127.0.0.1注释掉# bindIp: 127.0.0.1或者改成bindIp: 0.0.0.0即可开启远程连接

SpringBoot之mongoTemplate的使用

1、引入springboot mongo依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2、mongo的IP和端口

在resources下的application.yml中加入如下内容,端口默认:27017

1
2
3
4
spring:
data:
mongodb:
uri: mongodb://172.16.0.192/test

3、使用mongoTemplate

###User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package cn.zysheep.springboot.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: User
* @Author: 三月三
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Long id;
private String userName;
private String passWord;
}

###UserRepository

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cn.zysheep.springboot.repository;

import cn.zysheep.springboot.entity.User;

/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: UserRepository
* @Author: 三月三
*/
public interface UserRepository {

public void saveUser(User user);

public void testFindAll() ;

public User findUserByUserName(String userName);

public long updateUser(User user);

public void deleteUserById(Long id);


}

###UserPerpositoryImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package cn.zysheep.springboot.repository.impl;

import cn.zysheep.springboot.entity.User;
import cn.zysheep.springboot.repository.UserRepository;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import org.springframework.stereotype.Component;


import java.util.List;

import static org.springframework.data.mongodb.core.query.Criteria.*;

/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: UserPerpositoryImpl
* @Author: 三月三
*/
@Component
public class UserPerpositoryImpl implements UserRepository {
@Autowired
private MongoTemplate mongoTemplate;

/**
* @author: 三月三
* @description: 保存
* @param: [user]
* @return: void
*/
@Override
public void saveUser(User user) {
mongoTemplate.insert(user);
}

/**
* @author: 三月三
* @description: 查找所有文档
* @param: []
* @return: void
*/
@Override
public void testFindAll() {
List<User> all = mongoTemplate.findAll(User.class);
all.forEach(System.out::println);
}

/**
* @author: 三月三
* @description: 根据名字查找
* @param: [userName]
* @return: cn.zysheep.springboot.entity.User
*/
@Override
public User findUserByUserName(String userName) {
Query query=new Query(Criteria.where("userName").is(userName));
User user = mongoTemplate.findOne(query , User.class);
return user;
}

/**
* @author: 三月三
* @description: 修改文档记录
* @param: [user]
* @return: long
*/
@Override
public long updateUser(User user) {
Query query=new Query(Criteria.where("id").is(user.getId()));
Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
//更新查询返回结果集的第一条
UpdateResult result =mongoTemplate.updateFirst(query,update,User.class);
//更新查询返回结果集的所有
// mongoTemplate.updateMulti(query,update,UserEntity.class);
if(result!=null)
return result.getMatchedCount();
else
return 0;
}

/**
* @author: 三月三
* @description: 根据id删除文档记录
* @param: [id]
* @return: void
*/
@Override
public void deleteUserById(Long id) {
Query query=new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query,User.class);
}

}

为了方便测试,封装了MongodbUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
package cn.zysheep.springboot.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;

import cn.zysheep.springboot.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;


/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: MongodbUtils
* @Author: 三月三
*/

@Component
public class MongodbUtils {

public static MongodbUtils mongodbUtil;

@PostConstruct
public void init() {
mongodbUtil = this;
mongodbUtil.mongoTemplate = this.mongoTemplate;
}

@Autowired
private MongoTemplate mongoTemplate;


/**
* 保存对象List到指定集合中
* <p>
* 也可以在实体类上使用@Document(collection=“集合名称”)指定集合名称,未指定则默认实体类的类名为集合名称
*
* @param entiys
*/
public static void saveAll(String collName, List<?> entiys) {
for (Object entiy : entiys) {
saveData(collName, entiy);
}
}


/**
* 保存单个对象到指定集合中
*
* @param collName 集合名称
* @param entiy 实体名称
*/
public static void saveOne(String collName, Object entiy) {
saveData(collName, entiy);
}

/**
* 根据id倒序查询 集合中的数据
*
* @param entiy 数据实体
* @param collName 集合名称
* @param direction 倒序/正序 Direction.DESC/ASC
* @param
*/
public static Object findSortById(Class<?> entiy, String collName, Sort.Direction direction) {
Query query = new Query().with(Sort.by(direction, "id"));
return mongodbUtil.mongoTemplate.find(query, entiy, collName);
}

/**
* 查询返回指定字段
*
* @param fields 需要返回的指定字段
* @param clazz 数据实体类class
* @param collName 集合名称
* @param map Map<查询条件key,查询条件value>
* <p>
* 返回字段的时候id默认为返回,不返回id则field设置 fieldObj.put("id",false)
* @return
*/
public static Object findDesignField(List<String> fields, Map<String, Object> map, Class<?> clazz, String collName, boolean returnId) {
Criteria criteria = null;
if (map.containsKey(null)) {
return "查询条件key不能为Null~";
}
for (String key : map.keySet()) {
criteria = Criteria.where(key).is(map.get(key));
}
Query query = new Query(criteria);
for (String field : fields) {
query.fields().include(field);
}
if (!returnId) {
query.fields().exclude("id");
}
return mongodbUtil.mongoTemplate.find(query, clazz, collName);
}


/**
* 查询指定集合中的所有数据
*
* @param entiy 数据实体类
* @param collName 集合名称
*/
public static Object findAll(Class<?> entiy, String collName) {
return mongodbUtil.mongoTemplate.findAll(entiy, collName);
}

/**
* 模糊查询 根据 key 可以到 collName 中进行模糊查询 并排序
*
* @param param 匹配的参数
* @param collName 集合名称
* @param direction Direction.desc /asc 倒序/正序
* @param sortField 排序字段
* @return
*/
public static Object findLikeByParam(String param, String collName, String sortField, Sort.Direction direction,Class<?> entiy) {
Pattern pattern = Pattern.compile("^.*" + param + ".*$", Pattern.CASE_INSENSITIVE);
Query query = new Query(Criteria.where("name").regex(pattern)).with(Sort.by(direction, sortField));
return mongodbUtil.mongoTemplate.find(query, entiy, collName);
}

/**
* 向指定集合设置索引
*
* @param collName 集合名称
* @param indexName 索引名称
* @param map map.put("添加索引的字段",Direction.ASC/DESC)
*/
public static void createIndex(String collName, String indexName, Map<String, Sort.Direction> map) throws Exception {
if (map.containsKey(null)) {
throw new Exception("添加索引的字段不能为null");
}
Index index = new Index().named(indexName);
for (String key : map.keySet()) {
index.on(key, map.get(key));
}
mongodbUtil.mongoTemplate.indexOps(collName).ensureIndex(index);
}

/**
* 获取指定集合中的索引信息
*
* @param collName 集合名称
* @return
*/
public static Object getIndexInfo(String collName) {
return mongodbUtil.mongoTemplate.indexOps(collName).getIndexInfo();
}


/**
* 根据索引名称删除索引
*
* @param indexName 索引名称
* @param collName 集合名称
*/
public static void removeIndexByName(String collName, String indexName) {
mongodbUtil.mongoTemplate.indexOps(collName).dropIndex(indexName);
}


/**
* 删除指定集合中得所有索引
*
* @param collName 集合名称
*/
public static void removeIndexByName(String collName) {
mongodbUtil.mongoTemplate.indexOps(collName).dropAllIndexes();
}

/**
* 根据指定key 和value到指定collName集合中删除数据
*
* @param key
* @param value
* @param collName
*/
public static void removeAllByParam(String key, String value, String collName) {
Criteria criteria = Criteria.where(key).is(value);
Query query = Query.query(criteria);
mongodbUtil.mongoTemplate.remove(query, collName);
}


/**
* 根据指定条件查询 并排序
*
* @param obj 数据对象
* @param map Map<"查询条件key",查询条件值> map
* @param collName 集合名称
* @return
*/
public static List<? extends Object> findSortByParam(Object obj, String collName, Map<String, Object> map, String sortField, Sort.Direction direction) {
if (map.containsKey(null)) {
return new ArrayList<>();
}
Criteria criteria = null;
criteria = getCriteria(criteria, map);
if (criteria == null) {
return new ArrayList<>();
}
Query query = Query.query(criteria).with(Sort.by(direction, sortField));
return mongodbUtil.mongoTemplate.find(query, obj.getClass(), collName);
}


/**
* 范围查询
* <p>
* 查询大于等于begin 小于等于end范围内条件匹配得数据并排序
*
* @param obj 数据对象
* @param collName 集合名称
* @param map Map<"查询条件key",查询条件值> map
* @param sortField 排序字段
* @param direction 排序方式 Direction.asc / Direction.desc
* @param rangeCriteria 示例: lt小于 lte 小于等于 gt大于 gte大于等于 eq等于 ne不等于
* <p>
* Criteria rangeCriteria=Criteria.where("createDate").gte(begin).lte(end));
* <p>
* createDate:数据库中的时间字段,gegin:起始时间 end:结束时间
* @return
*/
public static List<? extends Object> findRangeByParam(Object obj, String collName, Map<String, Object> map,
String sortField, Sort.Direction direction, Criteria rangeCriteria) {
if (map.containsKey(null)) {
return new ArrayList<>();
}
Criteria criteria = null;
criteria = getCriteria(criteria, map);
if (criteria == null) {
return new ArrayList<>();
}
Query query = new Query().addCriteria(rangeCriteria).addCriteria(criteria).with(Sort.by(direction, sortField));
return mongodbUtil.mongoTemplate.find(query, obj.getClass(), collName);
}


/**
* 根据指定key value到指定集合中查询匹配得数量
*
* @param collName
* @param key
* @param value
* @return
*/
public static long count(String collName, String key, String value) {
Query query = Query.query(Criteria.where(key).is(value));
return mongodbUtil.mongoTemplate.count(query, "goods");
}


/**
* 在指定范围内查询匹配条件的数量
*
* @param clazz 数据实体类
* @param collName 集合名称
* @param map 查询条件map
* @param rangeCriteria 范围条件 Criteria rangeCriteria= Criteria.where("数据库字段").gt/gte(起始范围).lt/lte(结束范围)
* @return
*/
public static Long countRangeCondition(Class<?> clazz, String collName, Criteria rangeCriteria, Map<String, Object> map) {
Criteria criteria = null;
if (map.containsKey(null)) {
return null;
}
for (String key : map.keySet()) {
criteria = Criteria.where(key).is(map.get(key));
}
Query query = new Query();
if (criteria != null) {
query.addCriteria(criteria);
}
query.addCriteria(rangeCriteria);
return mongodbUtil.mongoTemplate.count(query, clazz, collName);
}


/**
* 指定集合 根据条件查询出符合的第一条数据
*
* @param entiy 数据对象
* @param map 条件map Map<条件key,条件value> map
* @param collectionName 集合名
* @return
*/
public static Object findSortFirst(Class<?> entiy, Map<String, Object> map, String collectionName, String field, Sort.Direction direction) {
if (map.containsKey(null)) {
return "查询条件不能为null~";
}
Criteria criteria = null;
criteria = getCriteria(criteria, map);
Query query = Query.query(criteria).with(Sort.by(direction, field));
return mongodbUtil.mongoTemplate.findOne(query, entiy, collectionName);
}

/**
* 指定集合 修改数据,且修改所找到的所有数据
*
* @param accordingKey 修改条件 key
* @param accordingValue 修改条件 value
* @param map Map<修改内容 key数组,修改内容 value数组>
* @param collName 集合名
* @param type 修改操作类型 1:修改第一条数据 0:修改所有匹配得数据
*/
public static void updateMulti(String accordingKey, Object accordingValue, Map<String, Object> map,
String collName, Integer type) {
if (map.containsKey(null)) {
return;
}
Criteria criteria = Criteria.where(accordingKey).is(accordingValue);
Query query = Query.query(criteria);
Update update = new Update();

for (String key : map.keySet()) {
update.set(key, map.get(key));
}
if (type == 1) {
mongodbUtil.mongoTemplate.updateFirst(query, update, collName);
} else {
mongodbUtil.mongoTemplate.updateMulti(query, update, collName);
}
}

/**
* 对某字段做sum求和
*
* @param clazz 数据实体类
* @param map Map<查询条件key,查询条件value> map
* @param collName 集合名称
* @param sumField 求和字段
* @param rangeCriteria 范围条件
* @return Criteria rangeCriteria = Criteria.where(字段).gt(起始范围).lt(结束范围)
*/
public static Object findSum(Class<?> clazz, Map<String, Object> map, String collName, String sumField, Criteria rangeCriteria) {
if (map.containsKey(null)) {
return "查询条件key不能为Null";
}
Criteria criteria = null;
MatchOperation match = null;
for (String key : map.keySet()) {
criteria = Criteria.where(key).is(map.get(key));
}
if (criteria != null) {
match = Aggregation.match(criteria);
}
GroupOperation count = Aggregation.group().sum(sumField).as(sumField);
return mongodbUtil.mongoTemplate.aggregate(Aggregation.newAggregation(match, count), collName, clazz).getMappedResults();
}

/**
* 分页查询
*
* @param entiy 数据实体类
* @param collName 集合名称
* @param map Map<"查询条件key",查询条件值> map 若 keys/values 为null,则查询集合中所有数据
* @param pageNo 当前页
* @param pageSize 当前页数据条数
* @param direction Direction.Desc/ASC 排序方式
* @param sortField 排序字段
* @return
*/
public static PageModel findSortPageCondition(Class<?> entiy, String collName, Map<String, Object> map,
int pageNo, int pageSize, Sort.Direction direction, String sortField) {

Criteria criteria = getCriteria(new Criteria(), map);

long count;

if (criteria == null) {
count = mongodbUtil.mongoTemplate.count(new Query(), entiy, collName);
} else {
count = mongodbUtil.mongoTemplate.count(new Query(criteria), entiy, collName);
}
int pages = (int) Math.ceil((double) count / (double) pageSize);
if (pageNo <= 0 || pageNo > pages) {
pageNo = 1;
}
int skip = pageSize * (pageNo - 1);
Query query = new Query().skip(skip).limit(pageSize);
query.with(Sort.by(direction, sortField));
if (criteria != null) {
query.addCriteria(criteria);
}
List<?> list = mongodbUtil.mongoTemplate.find(query, entiy, collName);
PageModel pageModel = new PageModel();
pageModel.setPageNo(pageNo);
pageModel.setPagesize(pageSize);
pageModel.setTotal(count);
pageModel.setPages(pages);
pageModel.setList(list);
return pageModel;
}

private static void saveData(String collName, Object entiy) {
if (StringUtils.isEmpty(collName)) {
mongodbUtil.mongoTemplate.save(entiy);
} else {
mongodbUtil.mongoTemplate.save(entiy, collName);
}
}

private static Criteria getCriteria(Criteria criteria, Map<String, Object> map) {
if (map == null) {
return null;
}
int i = 0;
for (String key : map.keySet()) {
if (i == 0) {
criteria = Criteria.where(key).is(map.get(key));
i++;
} else {
criteria.and(key).is(map.get(key));
}
}
return criteria;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package cn.zysheep.springboot.utils;

import java.io.Serializable;
import java.util.List;

/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: PageModel
* @Author: 三月三
*/
public class PageModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 当前页
*/
private Integer pageNo = 1;
/**
* 当前页条数
*/
private Integer pagesize = 10;
/**
* 总共的条数
*/
private Long total;
/**
* 总共的页数
*/
private Integer pages;
/**
* 实体类集合
*/
private List<?> list;

public Integer getPageNo() {
return pageNo;
}

public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}

public Integer getPagesize() {
return pagesize;
}

public void setPagesize(Integer pagesize) {
this.pagesize = pagesize;
}

public Long getTotal() {
return total;
}

/**
* 总数由0开始计数
* @param total
*/
public void setTotal(Long total) {
this.total = total + 1;
}

public Integer getPages() {
return pages;
}

public void setPages(Integer pages) {
this.pages = pages;
}

public List<?> getList() {
return list;
}

public void setList(List<?> list) {
this.list = list;
}

public PageModel(Integer pageNo, Integer pagesize, Long total, Integer pages, List<?> list) {
this.pageNo = pageNo;
this.pagesize = pagesize;
this.total = total;
this.pages = pages;
this.list = list;
}

public PageModel() {
}

@Override
public String toString() {
return "PageModel{" +
"pageNo=" + pageNo +
", pagesize=" + pagesize +
", total=" + total +
", pages=" + pages +
", list=" + list +
'}';
}
}

###测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package cn.zysheep.springboot;

import cn.zysheep.springboot.entity.User;
import cn.zysheep.springboot.repository.UserRepository;
import cn.zysheep.springboot.utils.MongodbUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest
class Springboot06DataMongodbApplicationTests {

@Autowired
private UserRepository userRepository;

@Autowired
private MongodbUtils mongodbUtils;

// 测试添加文档
@Test
public void testSaveUser() throws Exception {
User user=new User();
user.setId(1l);
user.setUserName("明世隐");
user.setPassWord("123456");
userRepository.saveUser(user);
}


// 测试根据名字查询文档
@Test
public void findUserByUserName(){
User user= userRepository.findUserByUserName("明世隐");
System.out.println("user is "+user);
}

// 测试修改文档
@Test
public void updateUser(){
User user=new User();
user.setId(2l);
user.setUserName("韩信");
user.setPassWord("123456789");
userRepository.updateUser(user);
}

// 测试删除
@Test
public void deleteUserById(){
userRepository.deleteUserById(1l);
}


@Test
void test1(){
List<User> user = (List<User>)MongodbUtils.findAll(User.class, "user");
user.forEach(System.out::println);
}


@Test
void test2(){
MongodbUtils.saveOne("user",new User(5L,"干将莫邪","123123"));
}


@Test
void test3(){
ArrayList<User> list = new ArrayList<>();

list.add(new User(6L,"荆轲","123123"));
list.add(new User(7L,"赵云","12312"));
list.add(new User(8L,"公孙离","asdfasdf"));
list.add(new User(9L,"伽罗","hdfgsdfg"));

MongodbUtils.saveAll("user",list);
}

}

多数据源 MongoDB 的使用

pom

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

yml

1
2
3
4
5
6
7
8
spring:
data:
mongodb:
host1: 172.16.0.192
host2: 172.16.0.192
dbName:
primaryDb: primary
secondaryDb: secondary

MongoConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package cn.zysheep.springboot.config;

import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;


/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: MongoConfig
* @Author: 三月三
*/
@Configuration
public class MongoConfig {
//读取配置文件里的值,部署后IP或者数据库名变化,不需重新打包
@Value("${spring.data.mongodb.host1}")
private String mongohost1;
@Value("${spring.data.mongodb.host2}")
private String mongohost2;
@Value("${spring.data.dbName.primaryDb}")
private String primaryDb;
@Value("${spring.data.dbName.secondaryDb}")
private String secondaryDb;
@Bean
@Primary
public MongoClient mongoClient() {
return new MongoClient(mongohost1);
}
@Bean
public MongoClient mongoClient2() {
return new MongoClient(mongohost2);
}

@Bean
@Primary
public MongoTemplate primaryMongoTemplate() {
return new MongoTemplate(mongoClient(), primaryDb);
}
@Bean
public MongoTemplate secondaryMongoTemplate() {
return new MongoTemplate(new SimpleMongoDbFactory(mongoClient(), secondaryDb));
}
}

Person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package cn.zysheep.springboot.entity;

import lombok.Data;
import org.springframework.stereotype.Component;

/**
* @version v1.0.0
* @ProjectName: springboot-learning-examples
* @ClassName: Person
* @Author: 三月三
*/

@Component
@Data
public class Person {
private String id;
private String name;
private int age;

public Person() {
}

public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package cn.zysheep.springboot;
import cn.zysheep.springboot.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import javax.annotation.Resource;

@SpringBootTest
class Springboot06DataMultiMongodb22XApplicationTests {
//这里用Resource,没有用Autoware
@Resource
private MongoTemplate primaryMongoTemplate;
@Resource
private MongoTemplate secondaryMongoTemplate;

//右键运行,看看两个库是否同时插入了数据
@Test
public void insert(){
Person p=new Person("001","tom",88);
primaryMongoTemplate.insert(p);
Person p2=new Person("N0012","zhangsan",14);
secondaryMongoTemplate.insert(p2);
}

@Test
public void queryon(){
Person qp = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class);
System.out.println(qp);
}

@Test
public void getOne(){
//不指定数据集,根据实体类的类名获取数据集。 这里Person也会被当作collectionName
Person zz = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class);
//指定数据集 同一个数据库下,建了一个user集合,跟person结构相同,这时就要指定了
Person one = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class,"primary");
System.out.println(one);
}
}